interface
와 type
은 모두 객체의 타입을 정의할 때 사용되자만,
용도와 표현력에서 약간의 차이가 있어 상황에 따라 선택적으로 사용하는 것이 좋습니다.
항목 | interface | type |
---|---|---|
목적 | 구조적인 객체 타입 선언 | 다양한 형태의 타입 정의 |
확장성 | extends 로 상속 가능 (객체 중심) | & 연산자로 확장 (모든 타입에 사용 가능) |
선언 병합 | O (자동 병합됨) | X (불가, 재정의 시 에러) |
표현력 | 객체 중심 | 유니언, 튜플, 조건부 타입 등 표현력 풍부 |
사용 추천 | 객체, 클래스 중심 구조 | 복합적, 유연한 타입 표현 시 |
interface
사용interface User {
id: number;
name: string;
isActive: boolean;
}
type
사용type User = {
id: number;
name: string;
isActive: boolean;
}
👉 동일한 결과를 내지만, 아래와 같은 상황에서 차이가 납니다.
extends
vs &
// interface
interface Person {
name: string;
}
interface Employee extends Person {
employeeId: number;
}
// type
type Person2 = { name: string; }
type Employee2 = Person2 & { employeeId: number };
✔️ 둘 다 확장 가능하지만, interface
는 객체 중심 계층화, type
은 범용 조합에 적합합니다.
interface Box {
size: number;
}
interface Box {
color: string;
}
// 최종 결과
// interface Box {
// size: number;
// color: string;
// }
⚠️ type
은 이름 중복 시 에러 발생 → 병합 불가
type Box = { size: number };
// ❌ Error: Duplicate identifier 'Box'
type Box = { color: string };
type Status = 'loading' | 'success' | 'error';
type Response =
| { status: 'loading' }
| { status: 'success'; data: string; }
| { status: 'error'; error: Error; };
✔️ type
은 다양한 구조와 조합이 필요한 복잡한 상황에 더 적합합니다.
✔️ interface
는 이런 유니언 타입을 표현할 수 없습니다.
상황 | 추천 | 이유 |
---|---|---|
React 컴포넌트 Props | ✅ interface | 확장성 좋고, 선언 병합가능 |
다양한 타입 조합 (유니언, 튜플 등) | ✅ type | 복잡한 타입 표현에 더 유연하고, 유니언 & 튜플 지원 |
객체 형태 정의 및 확장 | ✅ interface | extends 키워드로 자연스러운 상속과 선언 병한 지원 |
기본 타입 별칭 정의 | ✅ type | 원시 타입, 유니언, 튜플, 조건부 타입 등 다양하게 정의 가능 |
선언 병합 필요할 때 | ✅ interface | 동일 이름의 인터페이스를 합쳐서 확장 가능 |
타입 조작 필요할 때 (맵드 타입 등) | ✅ type | 조건부 타입, 유틸리티 타입, 맵드 타입 작성에 유리 |
기존 JS 코드와 호환성 고려 | ✅ interface | JS 객체 형태를 정의하는데 직관적이고, IDE 지원도 좋음 |
interface ButtonProps {
label: string;
onClick: () => void;
}
const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
<button onClick={onClick}>{label}</button>
);
✔️ 선언 병합 가능해서 Props를 확장하기 편합니다.
type Status = "loading" | "success" | "error";
type ResponseData = [number, string];
type Result = {
status: Status;
data: ResponseData;
};
✔️ 유니언 타입이나 튜플을 표현하기 편합니다.
interface User {
id: number;
name: string;
}
interface User {
email: string; // 선언 병합으로 자동 추가됨
}
interface Admin extends User {
role: string;
}
const admin: Admin = {
id: 1,
name: "Alice",
email: "alice@example.com",
role: "admin",
};
✔️ 선언 병합과 extends로 객체 확장이 자연스럽습니다.
type Nullable<T> = T | null;
type User = {
id: number;
name: string;
};
type NullableUser = Nullable<User>; // User | null
type Keys = keyof User; // "id" | "name"
✔️ 제네릭과 조건부 타입, 맵드 타입 등 타입 조작에 용이합니다.